//
//  InMemoryFileSystemTests.cpp
//  FuseSQLite
//
//  Created by Admin on 6/8/14.
//  Copyright (c) 2014 Admin. All rights reserved.
//

#include <gtest/gtest.h>

#include "InMemoryFileSystem.h"

TEST(FsTreeNode, create_directory_node)
{
    FsTreeNode dirNode("test", true);
    
    EXPECT_EQ("test", dirNode.name);
    EXPECT_EQ(0777 | S_IFDIR, dirNode.stat.st_mode);
    EXPECT_EQ(1, dirNode.stat.st_nlink);
    EXPECT_EQ(nullptr, dirNode.fileData.get());
}

TEST(FsTreeNode, create_file_node)
{
    FsTreeNode fileNode("test", false);
    
    EXPECT_EQ("test", fileNode.name);
    EXPECT_EQ(0777 | S_IFREG, fileNode.stat.st_mode);
    EXPECT_EQ(1, fileNode.stat.st_nlink);
    EXPECT_NE(nullptr, fileNode.fileData.get());
}

TEST(InMemoryFileSystem, createWithEmptyRoot)
{
    InMemoryFileSystem fileSystem;
    
    std::vector<FileInfo> childrens;
    bool ok = fileSystem.readDirectory("/", &childrens);
    
    EXPECT_TRUE(ok);
    EXPECT_EQ(childrens.size(), 2);
    
    EXPECT_EQ(".", childrens[0].name);
    EXPECT_EQ("..", childrens[1].name);
}

TEST(InMemoryFileSystem, createExistingDir)
{
    InMemoryFileSystem fileSystem;
    
    bool created = fileSystem.createDirectory("/", 0777);
    EXPECT_FALSE(created);
}

TEST(InMemoryFileSystem, createDirWithBadPath)
{
    InMemoryFileSystem fileSystem;
    
    bool created = fileSystem.createDirectory("/test/test1", 0777);
    EXPECT_FALSE(created);
}

TEST(InMemoryFileSystem, createDirInRoot)
{
    InMemoryFileSystem fileSystem;
    
    bool created = fileSystem.createDirectory("/test", 0777);
    EXPECT_TRUE(created);
    
    std::vector<FileInfo> childrens;
    bool ok = fileSystem.readDirectory("/", &childrens);
    
    ASSERT_TRUE(ok);
    ASSERT_EQ(childrens.size(), 3);
    
    EXPECT_EQ(".", childrens[0].name);
    EXPECT_EQ("..", childrens[1].name);
    EXPECT_EQ("test", childrens[2].name);
}

TEST(InMemoryFileSystem, createDirInDir)
{
    InMemoryFileSystem fileSystem;
    
    fileSystem.createDirectory("/test", 0777);
    bool created = fileSystem.createDirectory("/test/test1", 0777);
    EXPECT_TRUE(created);
    
    std::vector<FileInfo> childrens;
    bool read = fileSystem.readDirectory("/test", &childrens);
    
    ASSERT_TRUE(read);
    ASSERT_EQ(childrens.size(), 3);
    
    EXPECT_EQ(".", childrens[0].name);
    EXPECT_EQ("..", childrens[1].name);
    EXPECT_EQ("test1", childrens[2].name);
}

TEST(InMemoryFileSystem, createSeveralDirsInRoot)
{
    InMemoryFileSystem fileSystem;
    
    fileSystem.createDirectory("/test", 0777);
    bool created = fileSystem.createDirectory("/test1", 0777);
    ASSERT_TRUE(created);
    
    std::vector<FileInfo> childrens;
    bool read = fileSystem.readDirectory("/", &childrens);
    
    ASSERT_TRUE(read);
    ASSERT_EQ(childrens.size(), 4);
    
    EXPECT_EQ("test", childrens[2].name);
    EXPECT_EQ("test1", childrens[3].name);
}

TEST(InMemoryFileSystem, renameDirectory)
{
    InMemoryFileSystem fileSystem;
    
    fileSystem.createDirectory("/test", 0777);
    
    bool renamed = fileSystem.renameDirectory("/test", "/test1");
    ASSERT_TRUE(renamed);
    
    std::vector<FileInfo> childrens;
    bool read = fileSystem.readDirectory("/", &childrens);
    
    ASSERT_TRUE(read);
    ASSERT_EQ(childrens.size(), 3);

    EXPECT_EQ("test1", childrens[2].name);
}

TEST(InMemoryFileSystem, renameDirectoryWithBadPath)
{
    InMemoryFileSystem fileSystem;
    
    fileSystem.createDirectory("/test", 0777);
    
    bool renamed = fileSystem.renameDirectory("/test1", "/test2");
    EXPECT_FALSE(renamed);
}


TEST(InMemoryFileSystem, remove)
{
    InMemoryFileSystem fileSystem;
    
    fileSystem.createDirectory("/test", 0777);
    bool removed = fileSystem.remove("/test");
    ASSERT_TRUE(removed);
    
    std::vector<FileInfo> childrens;
    bool read = fileSystem.readDirectory("/", &childrens);
    
    ASSERT_TRUE(read);
    ASSERT_EQ(childrens.size(), 2);
}


TEST(InMemoryFileSystem, removeWithBadPath)
{
    InMemoryFileSystem fileSystem;
    
    bool removed = fileSystem.remove("/test");
    EXPECT_FALSE(removed);
}

TEST(InMemoryFileSystem, removeRoot)
{
    InMemoryFileSystem fileSystem;
    
    bool removed = fileSystem.remove("/");
    EXPECT_FALSE(removed);
}

TEST(InMemoryFileSystem, getAttributesOfRoot)
{
    InMemoryFileSystem fileSystem;
    
    struct stat stat;
    bool got = fileSystem.getAttributes("/", &stat);
    
    ASSERT_TRUE(got);
    
    EXPECT_EQ(stat.st_mode, S_IFDIR | 0777);
    EXPECT_EQ(stat.st_nlink, 1);
}

TEST(InMemoryFileSystem, getAttributesOfDir)
{
    InMemoryFileSystem fileSystem;
    
    fileSystem.createDirectory("/test", 0777);
    
    struct stat stat;
    bool got = fileSystem.getAttributes("/test", &stat);
    
    ASSERT_TRUE(got);
    
    EXPECT_EQ(stat.st_mode, S_IFDIR | 0777);
    EXPECT_EQ(stat.st_nlink, 1);
}

TEST(InMemoryFileSystem, getAttributesWithBadPath)
{
    InMemoryFileSystem fileSystem;
        
    struct stat stat;
    bool got = fileSystem.getAttributes("/test", &stat);
    
    ASSERT_FALSE(got);
}

TEST(InMemoryFileSystem, createFile)
{
    InMemoryFileSystem fileSystem;

    std::unique_ptr<InMemoryFile> outFile;
    bool created = fileSystem.createFile("/test_file", &outFile);
    ASSERT_TRUE(created);
    
    struct stat stat;
    bool got = fileSystem.getAttributes("/test_file", &stat);
    ASSERT_TRUE(got);
    
    EXPECT_EQ(0777 | S_IFREG, stat.st_mode);
    EXPECT_NE(nullptr, outFile.get());
}

TEST(InMemoryFileSystem, createFileWithBadPath)
{
    InMemoryFileSystem fileSystem;
    
    std::unique_ptr<InMemoryFile> outFile;
    bool created = fileSystem.createFile("/test/test_file", &outFile);
    ASSERT_FALSE(created);
}

TEST(InMemoryFileSystem, open_not_existing_file)
{
    InMemoryFileSystem fileSystem;
    
    std::unique_ptr<InMemoryFile> file;
    bool opened = fileSystem.openFile("/test_file", &file);

    ASSERT_FALSE(opened);
    EXPECT_EQ(nullptr, file.get());
}

TEST(InMemoryFileSystem, open_existing_file)
{
    InMemoryFileSystem fileSystem;
    
    std::unique_ptr<InMemoryFile> file;
    fileSystem.createFile("/test_file", &file);
    
    bool opened = fileSystem.openFile("/test_file", &file);
    ASSERT_TRUE(opened);
    
    EXPECT_NE(nullptr, file.get());
}

TEST(InMemoryFileSystem, truncate_file)
{
    InMemoryFileSystem fileSystem;
    struct stat stat;
    std::unique_ptr<InMemoryFile> file;
    
    fileSystem.createFile("/test", &file);
    
    bool truncated = fileSystem.truncateFile("/test", 10);
    ASSERT_TRUE(truncated);

    fileSystem.getAttributes("/test", &stat);
    EXPECT_EQ(10, stat.st_size);

    truncated = fileSystem.truncateFile("/test", 0);
    fileSystem.getAttributes("/test", &stat);
    EXPECT_EQ(0, stat.st_size);
}

TEST(InMemoryFileSystem, truncate_file_with_bad_path)
{
    InMemoryFileSystem fileSystem;
    
    bool truncated = fileSystem.truncateFile("/test", 10);
    ASSERT_FALSE(truncated);
}

TEST(InMemoryFileSystem, truncate_size_of_directory)
{
    InMemoryFileSystem fileSystem;
    
    bool truncated = fileSystem.truncateFile("/", 10);
    ASSERT_FALSE(truncated);
}
